package com.adcc.monitoragent.show.service;

import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.adcc.monitoragent.bean.BaseBean;
import com.adcc.monitoragent.bean.DatabaseBean;
import com.adcc.monitoragent.bean.MongoBean;
import com.adcc.monitoragent.bean.MqBean;
import com.adcc.monitoragent.bean.MqBean.MqMetricsBean;
import com.adcc.monitoragent.bean.OsBean;
import com.adcc.monitoragent.bean.OsBean.Disk;
import com.adcc.monitoragent.bean.RedisBean;
import com.adcc.monitoragent.bean.ServiceBean;
import com.adcc.monitoragent.bean.ServiceLogBean;
import com.adcc.monitoragent.bean.ZookeeperBean;
import com.adcc.monitoragent.show.bean.ClusterBean;
import com.adcc.monitoragent.show.bean.ClusterDeployBean;
import com.adcc.monitoragent.show.bean.DeployBean;
import com.adcc.monitoragent.show.bean.LogBean;
import com.adcc.monitoragent.show.bean.ServiceGroupBean;
import com.adcc.monitoragent.show.bean.WatchBean;
import com.adcc.monitoragent.util.Constants;
import com.adcc.monitoragent.util.FileUtil;
import com.adcc.monitoragent.util.JsonUtil;
import com.adcc.monitoragent.util.ProtertiesUtil;


/**
 * 消息处理
 * @author charlie
 *
 */
public class MessageService {
	private final static Logger log = LoggerFactory
			.getLogger(MessageService.class);
	
	private final static Logger clusterLogOne = LoggerFactory
			.getLogger("clusterLogOne");
	private final static Logger clusterLogTwo = LoggerFactory
			.getLogger("clusterLogTwo");
	
	/**
	 * 缓存mqbean用于做计算
	 */
	private static Map<String, MqBean> mqMap = new ConcurrentHashMap<String, MqBean>();
	/**
	 * 线程汇总数据，这个对广播的数据进行收集
	 */
	public static void sumMessageThread() {
		//集群一日志加载
		try {
			List<String> list = FileUtil.readLogFile(ProtertiesUtil.getShowLogPathParent() + ProtertiesUtil.getShowLogPaths().get(0).toString());
			for (String string : list) {
				//转日志对象
				ServiceLogBean log = (ServiceLogBean)JsonUtil.jsonToBean(string);
				WatchBean.getLogListMap().get(ProtertiesUtil.getShowClusterNames().get(0)).getServiceLogList().add(log);
			}
		} catch (Exception e) {
			log.error("历史日志1读取异常", e);
		}
		
		//超时检测线程 20秒一次
		new Thread(new Runnable() {
			@Override
			public void run() {
				while(true) {
					try {
						for (Map.Entry<String, ClusterBean> entry : WatchBean.getClusterListMap().entrySet()) {
							ClusterBean clusterBean = entry.getValue();
							for (BaseBean bean : clusterBean.getOsMap().values()) {
								timeOutCheck(bean);
							}
							for (BaseBean bean : clusterBean.getZkMap().values()) {
								timeOutCheck(bean);
							}
							for (ServiceGroupBean group : clusterBean.getServiceGroupMap().values()) {
								for (BaseBean bean : group.getServiceMap().values()) {
									timeOutCheck(bean);
								}
							}
							for (MqBean bean : clusterBean.getMqMap().values()) {
								timeOutCheck(bean);
								for (BaseBean metrics : bean.getMetrics()) {
									timeOutCheck(metrics);
								}
							}
							for (BaseBean bean : clusterBean.getDbMap().values()) {
								timeOutCheck(bean);
							}
							for (BaseBean bean : clusterBean.getRedisMap().values()) {
								timeOutCheck(bean);
							}
							for (BaseBean bean : clusterBean.getMongoMap().values()) {
								timeOutCheck(bean);
							}
						}
						//日志清理
						for (Map.Entry<String, LogBean> entry : WatchBean.getLogListMap().entrySet()) {
							LogBean logBean = entry.getValue();
							if(logBean.getServiceLogList().size() > 10000) {
								for (int i = 0; i < 1000; i++) {
									try {
										logBean.getServiceLogList().remove(logBean.getServiceLogList().size() - 1);
									} catch (Exception e) {
										log.error("日志清除异常:" + e.getMessage());
									}
								}
							}
						}
					} catch (Exception e) {
						log.error("超时检测异常:" + e.getMessage());
					}
					
					try {
						Thread.sleep(10000);
					} catch (InterruptedException e) {
						log.error("休眠异常:" + e.getMessage());
					}
				}
			}
		}).start();
		
	}
	/**
	 * 获取最新监控数据
	 * @return
	 */
	public static WatchBean getNewWatchBean() {
		return null;
	}
	/**
	 * 超时检测
	 * @param bean
	 */
	private static void timeOutCheck(BaseBean bean) {
		if(System.currentTimeMillis() - bean.getReciveTime().getTime() > 30000) {
			bean.setStatus(Constants.STATUS_ERROR);
			bean.setSumStatus(Constants.SUM_STATUS_OUTTIME);
			bean.setSumStatusMsg("超时");
			bean.setShowType(bean.getFixType() + "_" + bean.getSumStatus());
		}
	}
	
	/**
	 * 监控消息
	 * @param obj
	 * @param bean
	 */
	public static void watchMsg(String name, Object obj) {
		ClusterBean bean = WatchBean.getClusterListMap().get(name);
		LogBean logBean = WatchBean.getLogListMap().get(name);
		ClusterDeployBean clusterDeployBean = WatchBean.getClusterDeployListMap().get(name);
		Logger clusterLog = clusterLogOne;
		if(!"cluster".equals(name)) {
			clusterLog = clusterLogTwo;
		}
		
		boolean showDynamic = ProtertiesUtil.isShowDynamic();
		if(obj instanceof DatabaseBean) {
			DatabaseBean b = (DatabaseBean)obj;
			if((!showDynamic && bean.getDbMap().get(b.buildKey()) != null) ||
					showDynamic) {
				bean.getDbMap().put(b.buildKey(), b);
				dbSum(b);
			}
		} else if(obj instanceof MongoBean) {
			MongoBean b = (MongoBean)obj;
			if((!showDynamic && bean.getMongoMap().get(b.buildKey()) != null) ||
					showDynamic) {
				bean.getMongoMap().put(b.buildKey(), b);
				mongoSum(b);
			}
			
		} else if(obj instanceof MqBean) {
			MqBean b = (MqBean)obj;
			if((!showDynamic && bean.getMqMap().get(b.buildKey()) != null) ||
					showDynamic) {
				mqMap.put(b.buildKey(), b);
				bean.getMqMap().put(b.buildKey(), b);
				mqSum(b);
			}
		} else if(obj instanceof OsBean) {
			OsBean b = (OsBean)obj;
			if((!showDynamic && bean.getOsMap().get(b.buildKey()) != null) ||
					showDynamic) {
				bean.getOsMap().put(b.buildKey(), b);
				osSum(b);
			}
		} else if(obj instanceof RedisBean) {
			RedisBean b = (RedisBean)obj;
			if((!showDynamic && bean.getRedisMap().get(b.buildKey()) != null) ||
					showDynamic) {
				bean.getRedisMap().put(b.buildKey(), b);
				redisSum(b);
			}
		} else if(obj instanceof ServiceBean) {
			ServiceBean b = (ServiceBean)obj;
			//构造组
			ServiceGroupBean group = bean.getServiceGroupMap().get(b.buildGroupName());
			if(showDynamic) {
				//构建组名称
				if(group == null) {
					group = new ServiceGroupBean(b.buildGroupName());
					bean.getServiceGroupMap().put(b.buildGroupName(), group);
				}
				group.getServiceMap().put(b.buildKey(), b);
				serviceSum(b);
			} else if(group != null && !showDynamic) {
				if(group.getServiceMap().get(b.buildKey()) != null) {
					group.getServiceMap().put(b.buildKey(), b);
					serviceSum(b);
				}
			}
		} else if(obj instanceof ServiceLogBean) {
			ServiceLogBean b = (ServiceLogBean)obj;
			logSum(b, clusterLog, logBean);
		} else if(obj instanceof ZookeeperBean) {
			ZookeeperBean b = (ZookeeperBean)obj;
			if((!showDynamic && bean.getZkMap().get(b.buildKey()) != null) ||
					showDynamic) {
				bean.getZkMap().put(b.buildKey(), b);
				zkSum(b);
			}
		}
		
		//设置接收时间   部署机器
		if(obj instanceof BaseBean) {
			BaseBean baseBean = (BaseBean)obj;
			baseBean.setReciveTime(new Date());
			String ip = baseBean.getIp();
			DeployBean deployBean = clusterDeployBean.getDeployMap().get(ip);
			if(deployBean == null && showDynamic) {
				deployBean = new DeployBean(ip);
				clusterDeployBean.getDeployMap().put(ip, deployBean);
			}
			if(deployBean != null) {
				if(baseBean instanceof OsBean) {//设置集群系统信息
					deployBean.setOsBean((OsBean)baseBean);
				} else {//设置集群其他应用
					if((!showDynamic && deployBean.getAppMap().get(baseBean.buildKey()) != null) ||
							showDynamic) {
						deployBean.getAppMap().put(baseBean.buildKey(), baseBean);
					}
				}
			}
		}
	}
	
	/**
	 * 日志汇总
	 * @param b
	 */
	private static void logSum(ServiceLogBean b, Logger clusterLog, LogBean logBean) {
		//记录特别的日志文件
		clusterLog.info(JsonUtil.beanToJson(b));
		logBean.getServiceLogList().add(b);
		
		//找出mq队列用户日志，然后单独记录到用户文件
		if(b.getServiceName().startsWith("queue-")){
			//记录文件  创建父目录   append 数据
			String path = ProtertiesUtil.getShowLogPathParent() + b.getServiceName() + "/";
			FileUtil.creatPath(path);
			FileUtil.write(path + "log.log", b.toString() + "\n", true);
		}
	}
	/**
	 * 操作系统状态汇总
	 * @param b
	 */
	private static void osSum(OsBean b) {
		//内存或cpu或磁盘 使用达到95%  warn
		
		double cpu = Double.parseDouble(b.getOsCpuRatio().replace("%", ""));
		if(cpu >= 95) {
			b.setSumStatus(Constants.SUM_STATUS_ERROR);
			b.setSumStatusMsg("cpu超负荷");
			b.setShowType(b.getFixType() + b.getSumStatus());
			return;
		}
		double memory = Double.parseDouble(b.getOsMemoryUsePercent().replace("%", ""));
		if(memory >= 95) {
			b.setSumStatus(Constants.SUM_STATUS_ERROR);
			b.setSumStatusMsg("内存超负荷");
			b.setShowType(b.getFixType() + b.getSumStatus());
			return;
		}
		for (Disk disk : b.getOsDiskList()) {
			if (disk.getUsePercent() == null) {
				return;
			}
			double di = Double.parseDouble(disk.getUsePercent().replace("%", ""));
			if(di >= 95) {
				b.setSumStatus(Constants.SUM_STATUS_ERROR);
				b.setSumStatusMsg("磁盘超负荷" + disk.getName());
				b.setShowType(b.getFixType() + b.getSumStatus());
				return;
			}
		}
		b.setSumStatus(Constants.SUM_STATUS_NORMAL);
		b.setSumStatusMsg("正常");
		b.setShowType(b.getFixType() + b.getSumStatus());
		b.setShowName();
	}
	
	/**
	 * 数据库状态汇总
	 * @param b
	 */
	private static void dbSum(DatabaseBean b) {
		//状态汇总
		String showType = b.getFixType() + "_";
		if(Constants.STATUS_OK.equals(b.getStatus())) {
			b.setSumStatus(Constants.SUM_STATUS_NORMAL);
			b.setSumStatusMsg("正常");
			showType += b.getSumStatus();
		} else {
			b.setSumStatus(Constants.SUM_STATUS_ERROR);
			b.setSumStatusMsg("异常");
			showType += b.getSumStatus();
		}
		//设置展现状态 db_1 db_3
		b.setShowType(showType);
		//设置名称
		b.setShowName();
	}
	/**
	 * mongo状态汇总
	 * @param b
	 */
	private static void mongoSum(MongoBean b) {
		//状态汇总
		String showType =  b.getFixType() + "_";
		if(Constants.STATUS_OK.equals(b.getStatus())) {
			b.setSumStatus(Constants.SUM_STATUS_NORMAL);
			b.setSumStatusMsg("正常");
			showType += b.getSumStatus();
		} else {
			b.setSumStatus(Constants.SUM_STATUS_ERROR);
			b.setSumStatusMsg("异常");
			showType += b.getSumStatus();
		}
		//设置展现状态 mongo_1 mongo_3
		b.setShowType(showType);
		//设置名称
		b.setShowName();
	}
	/**
	 * mq状态汇总
	 * @param b
	 */
	private static void mqSum(MqBean b) {
		//获取其对应的集群  并把队列信息组装成map
		MqBean clusterBean = mqMap.get(b.buildClusterKey());
		//对应的上一次报文
		MqBean lastBean = mqMap.get(b.buildKey());
		Map<String, MqMetricsBean> mapClusterMetrics = new HashMap<String, MqMetricsBean>();
		Map<String, MqMetricsBean> mapLastMetrics = new HashMap<String, MqMetricsBean>();
		if(clusterBean != null) {
			for (MqMetricsBean mqMetricsBean : clusterBean.getMetrics()) {
				mapClusterMetrics.put(mqMetricsBean.buildKey(), mqMetricsBean);
			}
		}
		if(lastBean != null) {
			for (MqMetricsBean mqMetricsBean : lastBean.getMetrics()) {
				mapLastMetrics.put(mqMetricsBean.buildKey(), mqMetricsBean);
			}
		}
		String showType =  b.getFixType() + "_";
		//整个状态汇总   
		if(Constants.STATUS_OK.equals(b.getStatus())) {
			b.setSumStatus(Constants.SUM_STATUS_NORMAL);
			b.setSumStatusMsg("正常");
			showType += b.getSumStatus();
		} else {
			b.setSumStatus(Constants.SUM_STATUS_ERROR);
			b.setSumStatusMsg("异常");
			showType += b.getSumStatus();
		}
		//设置展现状态 mq_1 mq_3
		b.setShowType(showType);
		//设置名称
		b.setShowName();
		//mq队列状态汇总
		//mq_metrics_0 mq_metrics_1 mq_metrics_2 mq_metrics_3 
		if(b.getMetrics().size() > 0 ) {
			for (int i = 0; i < b.getMetrics().size(); i++) {
				MqMetricsBean mqm = b.getMetrics().get(i);
				String showMetricsType =  mqm.getFixType() + "_";
				//设置接收时间
				mqm.setReciveTime(new Date());
				String showName = WatchBean.getInterestMqMetrics().get(mqm.buildKey());
				if(showName != null) {//是关心队列
					//首先判断队列是否启用
					String[] temp = showName.split(":");
					showName = temp[1];
					mqm.setShowName(showName);//展现名称设置
					if("false".equals(temp[2])) {
						mqm.setSumStatus(Constants.SUM_STATUS_NOTENABLE);
						mqm.setSumStatusMsg("用户关闭");
						mqm.setShowType(showMetricsType + mqm.getSumStatus());
						continue;
					}
					
					//获取集群信息
					MqMetricsBean mqMCluster = mapClusterMetrics.get(mqm.buildKey());
					long clusterConsumer = -1;
					if(mqMCluster != null) {
						//集群消费者数量
						clusterConsumer = Long.parseLong(mqMCluster.getConsumer());
					}
					
					//堆报的时候黄色    没有消费者红色     报文数负数红色    正常绿色
					if(Long.parseLong(mqm.getConsumer()) <= 0) {//没有消费者
						//东方通集群只要有一个队列有消费者就行
						if(b.getType().equals(MqBean.MQ_TYPE_TLRT)) {
							if(clusterConsumer <= 0) {//消费者断开
								//设置本mq
								mqm.setSumStatus(Constants.SUM_STATUS_ERROR);
								mqm.setSumStatusMsg("消费者断开");
								mqm.setShowType(showMetricsType + mqm.getSumStatus());
								//设置集群mq
								if(mqMCluster != null) {
									mqMCluster.setSumStatus(mqm.getSumStatus());
									mqMCluster.setSumStatusMsg(mqm.getSumStatusMsg());
									mqMCluster.setShowType(mqm.getShowType());
								}
								continue;
							} else {//消费者在另外mq上
								//设置本mq
								mqm.setSumStatus(mqMCluster.getSumStatus());
								mqm.setSumStatusMsg(mqMCluster.getSumStatusMsg());
								mqm.setShowType(mqMCluster.getShowType());
							}
						} else {
							mqm.setSumStatus(Constants.SUM_STATUS_ERROR);
							mqm.setSumStatusMsg("消费者断开");
							mqm.setShowType(showMetricsType + mqm.getSumStatus());
							continue;
						}
					} else {
						if(Long.parseLong(mqm.getSize()) >= ProtertiesUtil.getMaxMqQueueNumber()) {//有消费者，报文积压,性能问题
							mqm.setSumStatus(Constants.SUM_STATUS_WARN);
							mqm.setSumStatusMsg("报文积压");
							mqm.setShowType(showMetricsType + mqm.getSumStatus());
						} else {
							mqm.setSumStatus(Constants.SUM_STATUS_NORMAL);//绿色：正常状态（报文正常发送至消息队列，并且消息队列的报文被正常收走）
							mqm.setSumStatusMsg("正常");
							mqm.setShowType(showMetricsType + mqm.getSumStatus());
						}
						//设置集群mq
						if(mqMCluster != null) {
							mqMCluster.setSumStatus(mqm.getSumStatus());
							mqMCluster.setSumStatusMsg(mqm.getSumStatusMsg());
							mqMCluster.setShowType(mqm.getShowType());
						}
					}
				} else {//不是关心队列      
					mqm.setShowName();//默认名称是队列名
					//默认白色     队报严重     黄色
					if(Long.parseLong(mqm.getSize()) <= 100000) {
						mqm.setSumStatus(Constants.SUM_STATUS_DISINTEREST);
						mqm.setShowType(showMetricsType + mqm.getSumStatus());
						mqm.setSumStatusMsg("队列未使用");
					} else {
						mqm.setSumStatus(Constants.SUM_STATUS_WARN);
						mqm.setSumStatusMsg("队列积压");
						mqm.setShowType(showMetricsType + mqm.getSumStatus());
					}
				}
			}
		}
		
	}
	/**
	 * redis状态汇总
	 * @param b
	 */
	private static void redisSum(RedisBean b) {
		//状态汇总
		String showType =  b.getFixType() + "_";
		if(Constants.STATUS_OK.equals(b.getStatus())) {
			b.setSumStatus(Constants.SUM_STATUS_NORMAL);
			b.setSumStatusMsg("正常");
			showType += b.getSumStatus();
		} else {
			b.setSumStatus(Constants.SUM_STATUS_ERROR);
			b.setSumStatusMsg("异常");
			showType += b.getSumStatus();
		}
		//设置展现状态 redis_1 redis_3
		b.setShowType(showType);
		//设置名称
		b.setShowName();
	}
	/**
	 * 服务状态汇总
	 * @param b
	 */
	private static void serviceSum(ServiceBean b) {
		//设置节点状态     状态，只有主备  或者没有信息
		String showType =  b.getFixType() + "_";
		if("SERVICE_CLUSTER".equals(b.getType())) {//主备集群
			if("LEADER".equals(b.getServiceClusterStatus())) {//主节点
				if("STOP".equals(b.getStatus())) {//异常
					b.setSumStatus(Constants.SUM_STATUS_ERROR);
					b.setSumStatusMsg("主节点停止");
				} else {//正常
					b.setSumStatus(Constants.SUM_STATUS_NORMAL);
					b.setSumStatusMsg("正常");
				}
				showType += b.getSumStatus() + "_" + Constants.MASTER;
			} else {//备节点
				if("STOP".equals(b.getStatus())) {//正常
					b.setSumStatus(Constants.SUM_STATUS_NORMAL);
					b.setSumStatusMsg("正常");
				} else {//异常
					b.setSumStatus(Constants.SUM_STATUS_ERROR);
					b.setSumStatusMsg("备节点启动");
				}
				showType += b.getSumStatus() + "_" + Constants.STANDBY;
			}
		} else {//并发集群
			if("STOP".equals(b.getStatus())) {//异常
				b.setSumStatus(Constants.SUM_STATUS_ERROR);
				b.setSumStatusMsg("并发节点停止");
			} else {//正常
				b.setSumStatus(Constants.SUM_STATUS_NORMAL);
				b.setSumStatusMsg("正常");
			}
			showType += b.getSumStatus();
		}
		//设置展现状态 service_1_m service_1_s | service_3_m service_3_s | service_1 service_3
		b.setShowType(showType);
		//设置名称
		b.setShowName();
	}
	/**
	 * zk状态汇总
	 * @param b
	 */
	private static void zkSum(ZookeeperBean b) {
		//状态汇总
		String showType =  b.getFixType() + "_";
		if(Constants.STATUS_OK.equals(b.getStatus())) {
			b.setSumStatus(Constants.SUM_STATUS_NORMAL);
			b.setSumStatusMsg("正常");
			if(null == b.getState() || "".equals(b.getState())) {
				showType += b.getSumStatus();
			} else {
				showType += b.getSumStatus() + "_" + b.getState();
			}
			
		} else {
			b.setSumStatus(Constants.SUM_STATUS_ERROR);
			b.setSumStatusMsg("异常");
			showType += b.getSumStatus();
		}
		//设置展现状态 zk_1_m   zk_1_s zk_1  zk_3
		b.setShowType(showType);
		//设置名称
		b.setShowName();
	}
}
